//Copyright 2010 Balazs Keri, Imre Keri
//
//This file is part of FireworksCreator.
//
//FireworksCreator is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//FireworksCreator is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with FireworksCreator.  If not, see <http://www.gnu.org/licenses/>.
//
#ifndef _PLAYER_PARTICLE_H
#define _PLAYER_PARTICLE_H
//
#include <global.h>
#include <vector>
#include <osg/GL>
#include "vec4evaluator.h"
#include "floatevaluator.h"
#include "emitterevaluator.h"
#include "particlesystem_fwd.h"
//
namespace player
{
class Particle
{
public:
   Particle();
   Particle(ParticleSystem *p_particle_system,unsigned int p_color_control_point_max, unsigned int p_alpha_control_point_max, unsigned int p_size_control_point_max, unsigned int p_radius_control_point_max,unsigned int p_emitter_evaluator_count);
   Particle(const Particle &p_other);
   Particle&operator=(const Particle &p_other);
   //
   void start();
   bool update(double p_dt);
   inline void kill();
   inline bool is_alive()const;
   inline double get_age()const;
   inline const osg::Vec4 &get_current_color()const;
   inline float get_current_alpha()const;
   inline float get_current_size()const;
   inline float get_current_mass()const;
   inline float get_current_mass_inv()const;
   inline float get_s_coord()const;
   inline float get_t_coord()const;
   //
   inline double get_life_time()const;
   inline void set_life_time(double p_life_time);
   inline const osg::Vec3 &get_position()const;
   inline void set_position(const osg::Vec3 &p_position);
   inline const osg::Vec3 &get_velocity()const;
   inline void set_velocity(const osg::Vec3 &p_velocity);
   inline const osg::Vec3 &get_angle()const;
   inline void set_angle(const osg::Vec3 &p_angle);
   inline const osg::Vec3 &get_angular_velocity()const;
   inline void set_angular_velocity(const osg::Vec3 &p_angular_velocity);
   void set_emitter_evaluator(unsigned int p_i,const EmitterEvaluator &p_emitter_evaluator);
   //
   void begin_render()const;
   void render(const osg::Vec3 &p_xpos,const osg::Vec3 &p_px,const osg::Vec3 &p_py,float p_scale=1.0f)const;
   void end_render()const;
   //
   //inline void transformPositionVelocity(const osg::Matrix& xform);
   //void transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r);
   //inline void transformAngleVelocity(const osg::Matrix& xform);
//   inline void setPreviousParticle(int previous)
//   {
//      _previousParticle = previous;
//   }
//   inline int getPreviousParticle() const
//   {
//      return _previousParticle;
//   }
//   inline void setNextParticle(int next)
//   {
//      _nextParticle = next;
//   }
//   inline int getNextParticle() const
//   {
//      return _nextParticle;
//   }
//   void setUpTexCoordsAsPartOfConnectedParticleSystem(ParticleSystem* ps);
   Vec4Evaluator color_evaluator;
   FloatEvaluator alpha_evaluator;
   FloatEvaluator size_evaluator;
   FloatEvaluator radius_evaluator;
protected:
   bool alive;
   bool mustdie;
   double t0;
   osg::Vec4 current_color;
   float current_alpha;
   float current_size;
   float current_radius;
   float current_mass;
   float current_massinv;
   //
   double life_time;
   osg::Vec3 position;
   osg::Vec3 prev_position;
   osg::Vec3 velocity;
   osg::Vec3 angle;
   osg::Vec3 prev_angle;
   osg::Vec3 angul_arvel;
   int current_tile;
   float s_coord;
   float t_coord;
   typedef std::vector<EmitterEvaluator> EmitterEvaluatorVector;
   EmitterEvaluatorVector emitter_evaluators;
   //
   ParticleSystem* system;
   // previous and next Particles are only used in ConnectedParticleSystems
   //int _previousParticle;
   //int _nextParticle;
};
//inline functions
inline void Particle::kill()
{
   mustdie=true;
}
inline bool Particle::is_alive()const
{
   return alive;
}
inline double Particle::get_age()const
{
   return t0;
}
inline const osg::Vec4 &Particle::get_current_color()const
{
   return current_color;
}
inline float Particle::get_current_alpha()const
{
   return current_alpha;
}
inline float Particle::get_current_size()const
{
   return current_size;
}
inline float Particle::get_current_mass()const
{
   return current_mass;
}
inline float Particle::get_current_mass_inv()const
{
   return current_massinv;
}
inline float Particle::get_s_coord()const
{
   return s_coord;
}
inline float Particle::get_t_coord()const
{
   return t_coord;
}
//
inline double Particle::get_life_time()const
{
   return life_time;
}
inline void Particle::set_life_time(double p_life_time)
{
   life_time=p_life_time;
}
inline const osg::Vec3 &Particle::get_position()const
{
   return position;
}
inline void Particle::set_position(const osg::Vec3 &p_position)
{
   position=p_position;
}
inline const osg::Vec3 &Particle::get_velocity()const
{
   return velocity;
}
inline void Particle::set_velocity(const osg::Vec3 &p_velocity)
{
   velocity=p_velocity;
}
inline const osg::Vec3 &Particle::get_angle()const
{
   return angle;
}
inline void Particle::set_angle(const osg::Vec3 &p_angle)
{
   angle=p_angle;
}
inline const osg::Vec3 &Particle::get_angular_velocity()const
{
   return angul_arvel;
}
inline void Particle::set_angular_velocity(const osg::Vec3 &p_angular_velocity)
{
   angul_arvel=p_angular_velocity;
}
//inline void Particle::transformPositionVelocity(const osg::Matrix& xform)
//{
//   _position = xform.preMult(_position);
//   _velocity = osg::Matrix::transform3x3(_velocity, xform);
//}
//inline void Particle::transformPositionVelocity(const osg::Matrix& xform1, const osg::Matrix& xform2, float r)
//{
//   osg::Vec3 position1 = xform1.preMult(_position);
//   osg::Vec3 velocity1 = osg::Matrix::transform3x3(_velocity, xform1);
//   osg::Vec3 position2 = xform2.preMult(_position);
//   osg::Vec3 velocity2 = osg::Matrix::transform3x3(_velocity, xform2);
//   float one_minus_r = 1.0f-r;
//   _position = position1*r+position2*one_minus_r;
//   _velocity = velocity1*r+velocity2*one_minus_r;
//}
//inline void Particle::transformAngleVelocity(const osg::Matrix& xform)
//{
//   // this should be optimized!
//
//   osg::Vec3 a1 = _angle+_angul_arvel;
//
//   _angle = xform.preMult(_angle);
//   a1 = xform.preMult(a1);
//
//   _angul_arvel = a1-_angle;
//}
}
//
#endif
